using Mono.Cecil;
using Mono.Cecil.Cil;

namespace Cil.Ast;

public sealed class ParameterSetExpression : SingleInstructionExpression
{
	public const int ValuePos = 0;
	public const int MaxNodes = 1;

	public ParameterSetExpression(Context context, Instruction position, ParameterReference ref_parameter, Expression exp_value)
		: base(context, position)
	{   
		if(ref_parameter.Index >= short.MaxValue) 
		{
			throw new ArgumentOutOfRangeException(string.Format("Method must not contain more than {0} parameters. Please, optimize your code.", short.MaxValue));
		}

		if(!ref_parameter.ParameterType.HardEquals(exp_value.ReturnType))
		{
			throw new InvalidOperationException(string.Format("parameter type '{0}' is not equals to value type '{1}'", ref_parameter.ParameterType.FullName, exp_value.ReturnType.FullName));
		}

		// base class
		ReadsStack = 1;
		WritesStack = 0;
		Nodes = new FixedList<Expression>(MaxNodes);

		ReturnType = Context.MakeRef(typeof(void));

		// this
		ParameterReference = ref_parameter;
		ValueExpression = exp_value;
	}

	public ParameterReference ParameterReference { get; private set; }

	public Expression ValueExpression { get { return Nodes[ValuePos]; } set { Nodes[ValuePos] = value; value.ParentNode = this; } }

	public override string ToString()
	{
		return string.Format("{0} = {1}{2}", ParameterReference, ValueExpression, FinalString);
	}
}

public static partial class IlAst
{
	public static ParameterSetExpression ParameterSet(Context context, Instruction position, ParameterReference ref_parameter, Expression exp_value)
	{
		return new ParameterSetExpression(context, position, ref_parameter, exp_value);
	}
}